package com.sc.admin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sc.admin.common.constant.SystemConstants;
import com.sc.admin.common.result.Result;
import com.sc.admin.common.result.ResultCodeEnum;
import com.sc.admin.common.util.DateUtils;
import com.sc.admin.common.util.ObjUtils;
import com.sc.admin.common.util.PasswordEncoderUtils;
import com.sc.admin.common.util.UserInfoUtils;
import com.sc.admin.converter.UserConverter;
import com.sc.admin.mapper.sys.SysUserMapper;
import com.sc.admin.model.bo.UserBO;
import com.sc.admin.model.bo.UserFormBO;
import com.sc.admin.model.dto.UserAuthInfo;
import com.sc.admin.model.entity.sys.SysUser;
import com.sc.admin.model.form.UserForm;
import com.sc.admin.model.form.UserInfoForm;
import com.sc.admin.model.form.UserPasswordForm;
import com.sc.admin.model.query.UserPageQuery;
import com.sc.admin.model.vo.UserExportVO;
import com.sc.admin.model.vo.UserInfoVO;
import com.sc.admin.model.vo.UserPageVO;
import com.sc.admin.model.vo.UserPersonInfoVO;
import com.sc.admin.service.SysMenuService;
import com.sc.admin.service.SysRoleService;
import com.sc.admin.service.SysUserRoleService;
import com.sc.admin.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户业务实现类
 *
 * @author shen chen
 * @since 2022/1/14
 */
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {


    private final SysUserRoleService userRoleService;

    private final UserConverter userConverter;

    private final SysMenuService menuService;

    private final SysRoleService roleService;


    /**
     * 获取用户分页列表
     *
     * @param queryParams
     * @return
     */
    @Override
    public IPage<UserPageVO> getUserPage(UserPageQuery queryParams) {

        // 参数构建
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<UserBO> page = new Page<>(pageNum, pageSize);

        // 格式化为数据库日期格式，避免日期比较使用格式化函数导致索引失效
        DateUtils.toDatabaseFormat(queryParams, "startTime", "endTime");

        // 查询数据
        Page<UserBO> userPage = this.baseMapper.getUserPage(page, queryParams);

        // 实体转换
        return userConverter.toPageVo(userPage);
    }

    /**
     * 获取用户详情
     *
     * @param userId
     * @return
     */
    @Override
    public UserForm getUserFormData(Long userId) {
        UserFormBO userFormBO = this.baseMapper.getUserDetail(userId);
        // 实体转换po->form
        UserForm userForm = userConverter.bo2Form(userFormBO);
        return userForm;
    }

    /**
     * 新增用户
     *
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    public boolean saveUser(UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        Assert.isTrue(count == 0, "用户名已存在");

        // 实体转换 form->entity
        SysUser entity = userConverter.form2Entity(userForm);

        // 设置默认加密密码
        String defaultEncryptPwd = PasswordEncoderUtils.encode(SystemConstants.DEFAULT_PASSWORD);
        entity.setPassword(defaultEncryptPwd);
        entity.setAvatar(SystemConstants.DEFAULT_AVATAR);

        // 新增用户
        boolean result = this.save(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 更新用户
     *
     * @param userId   用户ID
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    @Transactional
    public boolean updateUser(Long userId, UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .ne(SysUser::getId, userId)
        );
        Assert.isTrue(count == 0, "用户名已存在");

        // form -> entity
        SysUser entity = userConverter.form2Entity(userForm);

        // 修改用户
        boolean result = this.updateById(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 删除用户
     *
     * @param idsStr 用户ID，多个以英文逗号(,)分割
     * @return
     */
    @Override
    public boolean deleteUsers(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.stream(idsStr.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        return this.removeByIds(ids);

    }

    /**
     * 修改用户密码
     *
     * @param userId   用户ID
     * @param password 用户密码
     * @return true|false
     */
    @Override
    public boolean updatePassword(Long userId, String password) {
        return this.update(new LambdaUpdateWrapper<SysUser>()
                .eq(SysUser::getId, userId)
                .set(SysUser::getPassword, PasswordEncoderUtils.encode(password))
        );
    }

    /**
     * 根据用户名获取认证信息
     *
     * @param username 用户名
     * @return 用户认证信息 {@link UserAuthInfo}
     */
    @Override
    public UserAuthInfo getUserAuthInfo(String username) {
        UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
        if (userAuthInfo != null) {
            List<String> roles = userAuthInfo.getRoles();
            Set<String> roleSets = new HashSet<>(roles);
            if (CollectionUtil.isNotEmpty(roles)) {
                Set<String> perms = menuService.listRolePerms(roleSets);
                userAuthInfo.setPerms(new ArrayList<>(perms));
            }

            // 获取最大范围的数据权限
            Integer dataScope = roleService.getMaximumDataScope(roleSets);
            userAuthInfo.setDataScope(dataScope);
        }
        return userAuthInfo;
    }


    /**
     * 获取导出用户列表
     *
     * @param queryParams
     * @return
     */
    @Override
    public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
        List<UserExportVO> list = this.baseMapper.listExportUsers(queryParams);
        return list;
    }

    /**
     * 获取登录用户信息
     *
     * @return {@link UserInfoVO}   用户信息
     */
    @Override
    public UserInfoVO getCurrentUserInfo() {


        // 获取登录用户基础信息
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, StpUtil.getLoginId())
                .select(
                        SysUser::getId,
                        SysUser::getUsername,
                        SysUser::getNickname,
                        SysUser::getAvatar
                )
        );
        // entity->VO
        UserInfoVO userInfoVO = userConverter.toUserInfoVo(user);

        // 用户角色集合
        List<String> roles = StpUtil.getRoleList();
        userInfoVO.setRoles(roles);

        // 用户权限集合
        if (CollectionUtil.isNotEmpty(roles)) {
            List<String> perms = StpUtil.getPermissionList();
            userInfoVO.setPerms(perms);
        }
        return userInfoVO;
    }

    @Override
    public UserPersonInfoVO getUserPersonInfo() {
        Long userId = UserInfoUtils.getUserId();
        if (ObjUtils.isEmpty(userId)) {
            return null;
        }

        return this.baseMapper.getUserPersonInfo(userId);
    }

    @Override
    public boolean updateUserInfo(UserInfoForm userForm) {
        int update = this.baseMapper.update(userConverter.toUser(userForm), Wrappers.lambdaUpdate(SysUser.class).eq(SysUser::getId, UserInfoUtils.getUserId()));
        return update > 0;
    }

    @Override
    public Result<Void> updatePassword(UserPasswordForm passwordForm) {
        // 效验原密码
        SysUser sysUser = this.baseMapper.selectOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getId, UserInfoUtils.getUserId()));
        if (ObjUtils.isEmpty(sysUser)) {
            return Result.failed(ResultCodeEnum.USER_NOT_EXIST);
        }
        if (!PasswordEncoderUtils.matches(passwordForm.getOldPassword(), sysUser.getPassword())) {
            return Result.failed(ResultCodeEnum.PASSWORD_ERROR);
        }

        // 效验新密码是否一致
        if (ObjUtils.notEquals(passwordForm.getNewPassword(), passwordForm.getConfirmPassword())) {
            return Result.failed(ResultCodeEnum.TWO_PASSWORD_ERROR);
        }
        // 效验新密码是否符合规则

        // 修改密码
        this.baseMapper.update(new SysUser().setPassword(PasswordEncoderUtils.encode(passwordForm.getNewPassword())),
                Wrappers.lambdaUpdate(SysUser.class).eq(SysUser::getId, UserInfoUtils.getUserId()));


        return Result.success();
    }


}
